/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2013.11.19                                          *
 *                                                                       *
 *************************************************************************/

//declaration header
#include "COMMON/mesh/MeshGroup.h"

//FreeMAPs headers
#include "COMMON/tbox/LogMessage.h"

namespace FreeMAPs
{

MeshGroup::MeshGroup()
{}



MeshGroup::~MeshGroup()
{
    this->clear();
}



void
MeshGroup::clear()
{
    d_node_groups.clear();
//    d_side_groups.clear();
//    d_edge_groups.clear();

//    d_elem_groups.clear();
//    d_subdomain_names.clear();
}


#if 0
void
MeshGroup::remove_empty_group()
{
    for (std::map<std::string, NodeGroup>::iterator pos = d_node_groups.begin();
            pos != d_node_groups.end();)
    {
        if (pos->second.is_empty())
        {
            d_boundary_names.erase_by_key (pos->first);
            pos = d_node_groups.erase (pos);
        }
        else
        {
            ++pos;
        }
    }

    for (std::map<std::string, SideGroup>::iterator pos = d_side_groups.begin();
            pos != d_side_groups.end();)
    {
        if (pos->second.is_empty())
        {
            d_boundary_names.erase_by_key (pos->first);
            pos = d_side_groups.erase (pos);
        }
        else
        {
            ++pos;
        }
    }

    for (std::map<std::string, EdgeGroup>::iterator pos = d_edge_groups.begin();
            pos != d_edge_groups.end();)
    {
        if (pos->second.is_empty())
        {
            d_boundary_names.erase_by_key (pos->first);
            pos = d_edge_groups.erase (pos);
        }
        else
        {
            ++pos;
        }
    }

    for (std::map<std::string, ElemGroup>::iterator pos = d_elem_groups.begin();
            pos != d_elem_groups.end();)
    {
        if (pos->second.is_empty())
        {
            d_subdomain_names.erase_by_key (pos->first);
            pos = d_elem_groups.erase (pos);
        }
        else
        {
            ++pos;
        }
    }
}



void
MeshGroup::renumber_nodes (
    const std::map<int, int>& node_id_map)
{
    for (std::map<std::string, NodeGroup>::iterator pos = d_node_groups.begin();
            pos != d_node_groups.end(); ++pos)
    {
        pos->second.renumber_nodes (node_id_map);
    }
}



void
MeshGroup::set_elem_subdomain_id (
    std::vector<Elem>& elems) const
{
    for (std::map<std::string, ElemGroup>::const_iterator pos = d_elem_groups.begin();
            pos != d_elem_groups.end(); ++pos)
    {
        const std::string& subdomain_name = pos->first;
        const int subdomain_id = d_subdomain_names.get_value (subdomain_name);
        const ElemGroup& elem_group = pos->second;

        for (ElemGroup::const_iterator pe = elem_group.begin();
                pe != elem_group.end(); ++pe)
        {
            const int elem_id = *pe;
            FREEMAPS_ASSERT_GE (elem_id, 0);
            FREEMAPS_ASSERT_LT (elem_id, elems.size());
            elems[elem_id].set_subdomain_id (subdomain_name, subdomain_id);
        }
    }
}



void
MeshGroup::set_subdomain_names(
    const std::vector<Elem>& elems)
{
    for (std::size_t pos = 0; pos < elems.size(); ++pos)
    {
        const Elem& elem = elems[pos];
        const std::string& sbd_name = elem.get_subdomain_name();
        const int sbd_id = elem.get_subdomain_id();
        if (!d_subdomain_names.has_pair (sbd_name, sbd_id))
        {
            d_subdomain_names.insert (sbd_name, sbd_id);
        }
    }
}



std::ostream&
operator << (
    std::ostream& os,
    const MeshGroup& rhs)
{
    std::ostringstream oss;

    os << "Node Groups\n{\n";
    for (std::map<std::string, NodeGroup>::const_iterator pos = rhs.d_node_groups.begin();
            pos != rhs.d_node_groups.end(); ++pos)
    {
        oss.str("");
        oss << pos->second;
        os << LogMessage::get_log_info (oss, ONE_TAB) << '\n';
    }
    os << "}\n\n";

    os << "Side Groups\n{\n";
    for (std::map<std::string, SideGroup>::const_iterator pos = rhs.d_side_groups.begin();
            pos != rhs.d_side_groups.end(); ++pos)
    {
        oss.str("");
        oss << pos->second;
        os << LogMessage::get_log_info (oss, ONE_TAB) << '\n';
    }
    os << "}\n\n";

    os << "Edge Groups\n{\n";
    for (std::map<std::string, EdgeGroup>::const_iterator pos = rhs.d_edge_groups.begin();
            pos != rhs.d_edge_groups.end(); ++pos)
    {
        oss.str("");
        oss << pos->second;
        os << LogMessage::get_log_info (oss, ONE_TAB) << '\n';
    }
    os << "}\n\n";

    os << "Elem Groups\n{\n";
    for (std::map<std::string, ElemGroup>::const_iterator pos = rhs.d_elem_groups.begin();
            pos != rhs.d_elem_groups.end(); ++pos)
    {
        oss.str("");
        oss << pos->second;
        os << LogMessage::get_log_info (oss, ONE_TAB) << '\n';
    }
    os << "}";

    return os;
}
#endif
} // namepsace FreeMAPs
